home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / lib / mozilla-firefox / include / xpcom / nsCOMPtr.h < prev    next >
C/C++ Source or Header  |  2006-05-08  |  47KB  |  1,650 lines

  1. /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* ***** BEGIN LICENSE BLOCK *****
  3.  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  4.  *
  5.  * The contents of this file are subject to the Mozilla Public License Version
  6.  * 1.1 (the "License"); you may not use this file except in compliance with
  7.  * the License. You may obtain a copy of the License at
  8.  * http://www.mozilla.org/MPL/
  9.  *
  10.  * Software distributed under the License is distributed on an "AS IS" basis,
  11.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12.  * for the specific language governing rights and limitations under the
  13.  * License.
  14.  *
  15.  * The Original Code is mozilla.org code.
  16.  *
  17.  * The Initial Developer of the Original Code is
  18.  * Netscape Communications Corporation.
  19.  * Portions created by the Initial Developer are Copyright (C) 1998
  20.  * the Initial Developer. All Rights Reserved.
  21.  *
  22.  * Contributor(s):
  23.  *   Scott Collins <scc@mozilla.org> (original author)
  24.  *   L. David Baron <dbaron@dbaron.org>
  25.  *
  26.  * Alternatively, the contents of this file may be used under the terms of
  27.  * either of the GNU General Public License Version 2 or later (the "GPL"),
  28.  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  29.  * in which case the provisions of the GPL or the LGPL are applicable instead
  30.  * of those above. If you wish to allow use of your version of this file only
  31.  * under the terms of either the GPL or the LGPL, and not to allow others to
  32.  * use your version of this file under the terms of the MPL, indicate your
  33.  * decision by deleting the provisions above and replace them with the notice
  34.  * and other provisions required by the GPL or the LGPL. If you do not delete
  35.  * the provisions above, a recipient may use your version of this file under
  36.  * the terms of any one of the MPL, the GPL or the LGPL.
  37.  *
  38.  * ***** END LICENSE BLOCK ***** */
  39.  
  40. #ifndef nsCOMPtr_h___
  41. #define nsCOMPtr_h___
  42.  
  43. /*
  44.   Having problems?
  45.   
  46.   See the User Manual at:
  47.     http://www.mozilla.org/projects/xpcom/nsCOMPtr.html
  48.  
  49.  
  50.   nsCOMPtr
  51.     better than a raw pointer
  52.   for owning objects
  53.                        -- scc
  54. */
  55.  
  56.  
  57.   // Wrapping includes can speed up compiles (see "Large Scale C++ Software Design")
  58. #ifndef nsDebug_h___
  59. #include "nsDebug.h"
  60.   // for |NS_PRECONDITION|
  61. #endif
  62.  
  63. #ifndef nsISupportsUtils_h__
  64. #include "nsISupportsUtils.h"
  65.   // for |nsresult|, |NS_ADDREF|, |NS_GET_IID| et al
  66. #endif
  67.  
  68. #ifndef nscore_h___
  69. #include "nscore.h"
  70.   // for |NS_..._CAST|, |NS_COM_GLUE|
  71. #endif
  72.  
  73.  
  74. /*
  75.   WARNING:
  76.     This file defines several macros for internal use only.  These macros begin with the
  77.     prefix |NSCAP_|.  Do not use these macros in your own code.  They are for internal use
  78.     only for cross-platform compatibility, and are subject to change without notice.
  79. */
  80.  
  81.  
  82. #ifdef _MSC_VER
  83.   #define NSCAP_FEATURE_INLINE_STARTASSIGNMENT
  84.     // under VC++, we win by inlining StartAssignment
  85.  
  86.     // Also under VC++, at the highest warning level, we are overwhelmed  with warnings
  87.     //  about (unused) inline functions being removed.  This is to be expected with
  88.     //  templates, so we disable the warning.
  89.   #pragma warning( disable: 4514 )
  90. #endif
  91.  
  92. #define NSCAP_FEATURE_USE_BASE
  93.  
  94. #ifdef NS_DEBUG
  95.   #define NSCAP_FEATURE_TEST_DONTQUERY_CASES
  96.   #undef NSCAP_FEATURE_USE_BASE
  97. //#define NSCAP_FEATURE_TEST_NONNULL_QUERY_SUCCEEDS
  98. #endif
  99.  
  100.   /*
  101.     |...TEST_DONTQUERY_CASES| and |...DEBUG_PTR_TYPES| introduce some code that is 
  102.     problematic on a select few of our platforms, e.g., QNX.  Therefore, I'm providing
  103.     a mechanism by which these features can be explicitly disabled from the command-line.
  104.   */
  105.  
  106. #ifdef NSCAP_DISABLE_TEST_DONTQUERY_CASES
  107.   #undef NSCAP_FEATURE_TEST_DONTQUERY_CASES
  108. #endif
  109.  
  110. #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
  111.   // Our use of nsCOMPtr_base::mRawPtr violates the C++ standard's aliasing
  112.   // rules. Mark it with the may_alias attribute so that gcc 3.3 and higher
  113.   // don't reorder instructions based on aliasing assumptions for
  114.   // this variable.  Fortunately, gcc versions < 3.3 do not do any
  115.   // optimizations that break nsCOMPtr.
  116.  
  117.   #define NS_MAY_ALIAS_PTR(t)    t*  __attribute__((__may_alias__))
  118. #else
  119.   #define NS_MAY_ALIAS_PTR(t)    t*
  120. #endif
  121.  
  122. #if defined(NSCAP_DISABLE_DEBUG_PTR_TYPES)
  123.   #define NSCAP_FEATURE_USE_BASE
  124. #endif
  125.  
  126.  
  127. #ifdef HAVE_CPP_BOOL
  128.   typedef bool NSCAP_BOOL;
  129. #else
  130.   typedef PRBool NSCAP_BOOL;
  131. #endif
  132.  
  133.  
  134.  
  135.  
  136.   /*
  137.     The following three macros (|NSCAP_ADDREF|, |NSCAP_RELEASE|, and |NSCAP_LOG_ASSIGNMENT|)
  138.       allow external clients the ability to add logging or other interesting debug facilities.
  139.       In fact, if you want |nsCOMPtr| to participate in the standard logging facility, you
  140.       provide (e.g., in "nsTraceRefcnt.h") suitable definitions
  141.  
  142.         #define NSCAP_ADDREF(this, ptr)         NS_ADDREF(ptr)
  143.         #define NSCAP_RELEASE(this, ptr)        NS_RELEASE(ptr)
  144.   */
  145.  
  146. #ifndef NSCAP_ADDREF
  147.   #define NSCAP_ADDREF(this, ptr)     (ptr)->AddRef()
  148. #endif
  149.  
  150. #ifndef NSCAP_RELEASE
  151.   #define NSCAP_RELEASE(this, ptr)    (ptr)->Release()
  152. #endif
  153.  
  154.   // Clients can define |NSCAP_LOG_ASSIGNMENT| to perform logging.
  155. #ifdef NSCAP_LOG_ASSIGNMENT
  156.     // Remember that |NSCAP_LOG_ASSIGNMENT| was defined by some client so that we know
  157.     //  to instantiate |~nsGetterAddRefs| in turn to note the external assignment into
  158.     //  the |nsCOMPtr|.
  159.   #define NSCAP_LOG_EXTERNAL_ASSIGNMENT
  160. #else
  161.     // ...otherwise, just strip it out of the code
  162.   #define NSCAP_LOG_ASSIGNMENT(this, ptr)
  163. #endif
  164.  
  165. #ifndef NSCAP_LOG_RELEASE
  166.   #define NSCAP_LOG_RELEASE(this, ptr)
  167. #endif
  168.  
  169.  
  170.  
  171.  
  172.   /*
  173.     WARNING:
  174.       VC++4.2 is very picky.  To compile under VC++4.2, the classes must be defined
  175.       in an order that satisfies:
  176.     
  177.         nsDerivedSafe < nsCOMPtr
  178.         already_AddRefed < nsCOMPtr
  179.         nsCOMPtr < nsGetterAddRefs
  180.  
  181.       The other compilers probably won't complain, so please don't reorder these
  182.       classes, on pain of breaking 4.2 compatibility.
  183.   */
  184.  
  185.  
  186. template <class T>
  187. class nsDerivedSafe : public T
  188.     /*
  189.       No client should ever see or have to type the name of this class.  It is the
  190.       artifact that makes it a compile-time error to call |AddRef| and |Release|
  191.       on a |nsCOMPtr|.  DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE.
  192.  
  193.       See |nsCOMPtr::operator->|, |nsCOMPtr::operator*|, et al.
  194.  
  195.       This type should be a nested class inside |nsCOMPtr<T>|.
  196.     */
  197.   {
  198.     private:
  199. #ifdef HAVE_CPP_ACCESS_CHANGING_USING
  200.       using T::AddRef;
  201.       using T::Release;
  202. #else
  203.       nsrefcnt AddRef(void);
  204.       nsrefcnt Release(void);
  205. #endif
  206.  
  207. #if !defined(AIX) && !defined(IRIX)
  208.       void operator delete( void*, size_t );                  // NOT TO BE IMPLEMENTED
  209.         // declaring |operator delete| private makes calling delete on an interface pointer a compile error
  210. #endif
  211.  
  212.       nsDerivedSafe<T>& operator=( const T& );                // NOT TO BE IMPLEMENTED
  213.         // you may not call |operator=()| through a dereferenced |nsCOMPtr|, because you'd get the wrong one
  214.  
  215.         /*
  216.           Compiler warnings and errors: nsDerivedSafe operator=() hides inherited operator=().
  217.           If you see that, that means somebody checked in a [XP]COM interface class that declares an
  218.           |operator=()|, and that's _bad_.  So bad, in fact, that this declaration exists explicitly
  219.           to stop people from doing it.
  220.         */
  221.  
  222.     protected:
  223.       nsDerivedSafe();                                        // NOT TO BE IMPLEMENTED
  224.         /*
  225.           This ctor exists to avoid compile errors and warnings about nsDeriviedSafe using the
  226.           default ctor but inheriting classes without an empty ctor. See bug 209667.
  227.         */
  228.   };
  229.  
  230. #if !defined(HAVE_CPP_ACCESS_CHANGING_USING) && defined(NEED_CPP_UNUSED_IMPLEMENTATIONS)
  231. template <class T>
  232. nsrefcnt
  233. nsDerivedSafe<T>::AddRef()
  234.   {
  235.     return 0;
  236.   }
  237.  
  238. template <class T>
  239. nsrefcnt
  240. nsDerivedSafe<T>::Release()
  241.   {
  242.     return 0;
  243.   }
  244.  
  245. #endif
  246.  
  247.  
  248.  
  249. template <class T>
  250. struct already_AddRefed
  251.     /*
  252.       ...cooperates with |nsCOMPtr| to allow you to assign in a pointer _without_
  253.       |AddRef|ing it.  You might want to use this as a return type from a function
  254.       that produces an already |AddRef|ed pointer as a result.
  255.  
  256.       See also |getter_AddRefs()|, |dont_AddRef()|, and |class nsGetterAddRefs|.
  257.  
  258.       This type should be a nested class inside |nsCOMPtr<T>|.
  259.  
  260.       Yes, |already_AddRefed| could have been implemented as an |nsCOMPtr_helper| to
  261.       avoid adding specialized machinery to |nsCOMPtr| ... but this is the simplest
  262.       case, and perhaps worth the savings in time and space that its specific
  263.       implementation affords over the more general solution offered by
  264.       |nsCOMPtr_helper|.
  265.     */
  266.   {
  267.     already_AddRefed( T* aRawPtr )
  268.         : mRawPtr(aRawPtr)
  269.       {
  270.         // nothing else to do here
  271.       }
  272.  
  273.     T* get() const { return mRawPtr; }
  274.  
  275.     T* mRawPtr;
  276.   };
  277.  
  278. template <class T>
  279. inline
  280. const already_AddRefed<T>
  281. getter_AddRefs( T* aRawPtr )
  282.     /*
  283.       ...makes typing easier, because it deduces the template type, e.g., 
  284.       you write |dont_AddRef(fooP)| instead of |already_AddRefed<IFoo>(fooP)|.
  285.     */
  286.   {
  287.     return already_AddRefed<T>(aRawPtr);
  288.   }
  289.  
  290. template <class T>
  291. inline
  292. const already_AddRefed<T>
  293. getter_AddRefs( const already_AddRefed<T> aAlreadyAddRefedPtr )
  294.   {
  295.     return aAlreadyAddRefedPtr;
  296.   }
  297.  
  298. template <class T>
  299. inline
  300. const already_AddRefed<T>
  301. dont_AddRef( T* aRawPtr )
  302.   {
  303.     return already_AddRefed<T>(aRawPtr);
  304.   }
  305.  
  306. template <class T>
  307. inline
  308. const already_AddRefed<T>
  309. dont_AddRef( const already_AddRefed<T> aAlreadyAddRefedPtr )
  310.   {
  311.     return aAlreadyAddRefedPtr;
  312.   }
  313.  
  314.  
  315.  
  316. class nsCOMPtr_helper
  317.     /*
  318.       An |nsCOMPtr_helper| transforms commonly called getters into typesafe forms
  319.       that are more convenient to call, and more efficient to use with |nsCOMPtr|s.
  320.       Good candidates for helpers are |QueryInterface()|, |CreateInstance()|, etc.
  321.  
  322.       Here are the rules for a helper:
  323.         - it implements |operator()| to produce an interface pointer
  324.         - (except for its name) |operator()| is a valid [XP]COM `getter'
  325.         - the interface pointer that it returns is already |AddRef()|ed (as from any good getter)
  326.         - it matches the type requested with the supplied |nsIID| argument
  327.         - its constructor provides an optional |nsresult*| that |operator()| can fill
  328.           in with an error when it is executed
  329.           
  330.       See |class nsGetInterface| for an example.
  331.     */
  332.   {
  333.     public:
  334.       virtual nsresult NS_FASTCALL operator()( const nsIID&, void** ) const = 0;
  335.   };
  336.  
  337. /*
  338.   |nsQueryInterface| could have been implemented as an |nsCOMPtr_helper| to
  339.   avoid adding specialized machinery in |nsCOMPtr|, But |do_QueryInterface|
  340.   is called often enough that the codesize savings are big enough to
  341.   warrant the specialcasing.
  342. */
  343.  
  344. class NS_COM_GLUE nsQueryInterface
  345.   {
  346.     public:
  347.       explicit
  348.       nsQueryInterface( nsISupports* aRawPtr )
  349.           : mRawPtr(aRawPtr)
  350.         {
  351.           // nothing else to do here
  352.         }
  353.  
  354.       nsresult NS_FASTCALL operator()( const nsIID& aIID, void** ) const;
  355.  
  356.     private:
  357.       nsISupports*  mRawPtr;
  358.   };
  359.  
  360. class NS_COM_GLUE nsQueryInterfaceWithError
  361.   {
  362.     public:
  363.       nsQueryInterfaceWithError( nsISupports* aRawPtr, nsresult* error )
  364.           : mRawPtr(aRawPtr),
  365.             mErrorPtr(error)
  366.         {
  367.           // nothing else to do here
  368.         }
  369.  
  370.       nsresult NS_FASTCALL operator()( const nsIID& aIID, void** ) const;
  371.  
  372.     private:
  373.       nsISupports*  mRawPtr;
  374.       nsresult*     mErrorPtr;
  375.   };
  376.  
  377. inline
  378. nsQueryInterface
  379. do_QueryInterface( nsISupports* aRawPtr )
  380.   {
  381.     return nsQueryInterface(aRawPtr);
  382.   }
  383.  
  384. inline
  385. nsQueryInterfaceWithError
  386. do_QueryInterface( nsISupports* aRawPtr, nsresult* error )
  387.   {
  388.     return nsQueryInterfaceWithError(aRawPtr, error);
  389.   }
  390.  
  391. template <class T>
  392. inline
  393. void
  394. do_QueryInterface( already_AddRefed<T>& )
  395.   {
  396.     // This signature exists soley to _stop_ you from doing the bad thing.
  397.     //  Saying |do_QueryInterface()| on a pointer that is not otherwise owned by
  398.     //  someone else is an automatic leak.  See <http://bugzilla.mozilla.org/show_bug.cgi?id=8221>.
  399.   }
  400.  
  401. template <class T>
  402. inline
  403. void
  404. do_QueryInterface( already_AddRefed<T>&, nsresult* )
  405.   {
  406.     // This signature exists soley to _stop_ you from doing the bad thing.
  407.     //  Saying |do_QueryInterface()| on a pointer that is not otherwise owned by
  408.     //  someone else is an automatic leak.  See <http://bugzilla.mozilla.org/show_bug.cgi?id=8221>.
  409.   }
  410.  
  411.  
  412. ////////////////////////////////////////////////////////////////////////////
  413. // Using servicemanager with COMPtrs
  414. class NS_COM_GLUE nsGetServiceByCID
  415. {
  416.  public:
  417.     nsGetServiceByCID(const nsCID& aCID)
  418.         : mCID(aCID)
  419.         {
  420.             // nothing else to do
  421.         }
  422.     
  423.     nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
  424.     
  425.  private:
  426.     const nsCID&                mCID;
  427. };
  428.  
  429. class NS_COM_GLUE nsGetServiceByCIDWithError
  430. {
  431.  public:
  432.     nsGetServiceByCIDWithError( const nsCID& aCID, nsresult* aErrorPtr )
  433.         : mCID(aCID),
  434.           mErrorPtr(aErrorPtr)
  435.         {
  436.             // nothing else to do
  437.         }
  438.     
  439.     nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
  440.     
  441.  private:
  442.     const nsCID&                mCID;
  443.     nsresult*                   mErrorPtr;
  444. };
  445.  
  446. class NS_COM_GLUE nsGetServiceByContractID
  447. {
  448.  public:
  449.     nsGetServiceByContractID(const char* aContractID)
  450.         : mContractID(aContractID)
  451.         {
  452.             // nothing else to do
  453.         }
  454.     
  455.     nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
  456.     
  457.  private:
  458.     const char*                 mContractID;
  459. };
  460.  
  461. class NS_COM_GLUE nsGetServiceByContractIDWithError
  462. {
  463.  public:
  464.     nsGetServiceByContractIDWithError(const char* aContractID, nsresult* aErrorPtr)
  465.         : mContractID(aContractID),
  466.           mErrorPtr(aErrorPtr)
  467.         {
  468.             // nothing else to do
  469.         }
  470.     
  471.     nsresult NS_FASTCALL operator()( const nsIID&, void** ) const;
  472.     
  473.  private:
  474.     const char*                 mContractID;
  475.     nsresult*                   mErrorPtr;
  476. };
  477.  
  478. class nsCOMPtr_base
  479.     /*
  480.       ...factors implementation for all template versions of |nsCOMPtr|.
  481.  
  482.       This should really be an |nsCOMPtr<nsISupports>|, but this wouldn't work
  483.       because unlike the
  484.  
  485.       Here's the way people normally do things like this
  486.       
  487.         template <class T> class Foo { ... };
  488.         template <> class Foo<void*> { ... };
  489.         template <class T> class Foo<T*> : private Foo<void*> { ... };
  490.     */
  491.   {
  492.     public:
  493.  
  494.       nsCOMPtr_base( nsISupports* rawPtr = 0 )
  495.           : mRawPtr(rawPtr)
  496.         {
  497.           // nothing else to do here
  498.         }
  499.  
  500.       NS_COM_GLUE NS_FASTCALL ~nsCOMPtr_base();
  501.  
  502.       NS_COM_GLUE void NS_FASTCALL   assign_with_AddRef( nsISupports* );
  503.       NS_COM_GLUE void NS_FASTCALL   assign_from_qi( const nsQueryInterface, const nsIID& );
  504.       NS_COM_GLUE void NS_FASTCALL   assign_from_qi_with_error( const nsQueryInterfaceWithError&, const nsIID& );
  505.       NS_COM_GLUE void NS_FASTCALL   assign_from_gs_cid( const nsGetServiceByCID, const nsIID& );
  506.       NS_COM_GLUE void NS_FASTCALL   assign_from_gs_cid_with_error( const nsGetServiceByCIDWithError&, const nsIID& );
  507.       NS_COM_GLUE void NS_FASTCALL   assign_from_gs_contractid( const nsGetServiceByContractID, const nsIID& );
  508.       NS_COM_GLUE void NS_FASTCALL   assign_from_gs_contractid_with_error( const nsGetServiceByContractIDWithError&, const nsIID& );
  509.       NS_COM_GLUE void NS_FASTCALL   assign_from_helper( const nsCOMPtr_helper&, const nsIID& );
  510.       NS_COM_GLUE void** NS_FASTCALL begin_assignment();
  511.  
  512.     protected:
  513.       NS_MAY_ALIAS_PTR(nsISupports) mRawPtr;
  514.  
  515.       void
  516.       assign_assuming_AddRef( nsISupports* newPtr )
  517.         {
  518.             /*
  519.               |AddRef()|ing the new value (before entering this function) before
  520.               |Release()|ing the old lets us safely ignore the self-assignment case.
  521.               We must, however, be careful only to |Release()| _after_ doing the
  522.               assignment, in case the |Release()| leads to our _own_ destruction,
  523.               which would, in turn, cause an incorrect second |Release()| of our old
  524.               pointer.  Thank <waterson@netscape.com> for discovering this.
  525.             */
  526.           nsISupports* oldPtr = mRawPtr;
  527.           mRawPtr = newPtr;
  528.           NSCAP_LOG_ASSIGNMENT(this, newPtr);
  529.           NSCAP_LOG_RELEASE(this, oldPtr);
  530.           if ( oldPtr )
  531.             NSCAP_RELEASE(this, oldPtr);
  532.         }
  533.   };
  534.  
  535. // template <class T> class nsGetterAddRefs;
  536.  
  537. template <class T>
  538. class nsCOMPtr
  539. #ifdef NSCAP_FEATURE_USE_BASE
  540.     : private nsCOMPtr_base
  541. #endif
  542.   {
  543.  
  544. #ifdef NSCAP_FEATURE_USE_BASE
  545.   #define NSCAP_CTOR_BASE(x) nsCOMPtr_base(x)
  546. #else
  547.   #define NSCAP_CTOR_BASE(x) mRawPtr(x)
  548.  
  549.     private:
  550.       void    assign_with_AddRef( nsISupports* );
  551.       void    assign_from_qi( const nsQueryInterface, const nsIID& );
  552.       void    assign_from_qi_with_error( const nsQueryInterfaceWithError&, const nsIID& );
  553.       void    assign_from_gs_cid( const nsGetServiceByCID, const nsIID& );
  554.       void    assign_from_gs_cid_with_error( const nsGetServiceByCIDWithError&, const nsIID& );
  555.       void    assign_from_gs_contractid( const nsGetServiceByContractID, const nsIID& );
  556.       void    assign_from_gs_contractid_with_error( const nsGetServiceByContractIDWithError&, const nsIID& );
  557.       void    assign_from_helper( const nsCOMPtr_helper&, const nsIID& );
  558.       void**  begin_assignment();
  559.  
  560.       void
  561.       assign_assuming_AddRef( T* newPtr )
  562.         {
  563.           T* oldPtr = mRawPtr;
  564.           mRawPtr = newPtr;
  565.           NSCAP_LOG_ASSIGNMENT(this, newPtr);
  566.           NSCAP_LOG_RELEASE(this, oldPtr);
  567.           if ( oldPtr )
  568.             NSCAP_RELEASE(this, oldPtr);
  569.         }
  570.  
  571.     private:
  572.       T* mRawPtr;
  573. #endif
  574.  
  575.     public:
  576.       typedef T element_type;
  577.       
  578. #ifndef NSCAP_FEATURE_USE_BASE
  579.      ~nsCOMPtr()
  580.         {
  581.           NSCAP_LOG_RELEASE(this, mRawPtr);
  582.           if ( mRawPtr )
  583.             NSCAP_RELEASE(this, mRawPtr);
  584.         }
  585. #endif
  586.  
  587. #ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES
  588.       void
  589.       Assert_NoQueryNeeded()
  590.         {
  591.           if ( mRawPtr )
  592.             {
  593.               nsCOMPtr<T> query_result( do_QueryInterface(mRawPtr) );
  594.               NS_ASSERTION(query_result.get() == mRawPtr, "QueryInterface needed");
  595.             }
  596.         }
  597.  
  598.   #define NSCAP_ASSERT_NO_QUERY_NEEDED() Assert_NoQueryNeeded();
  599. #else
  600.   #define NSCAP_ASSERT_NO_QUERY_NEEDED()
  601. #endif
  602.  
  603.  
  604.         // Constructors
  605.  
  606.       nsCOMPtr()
  607.             : NSCAP_CTOR_BASE(0)
  608.           // default constructor
  609.         {
  610.           NSCAP_LOG_ASSIGNMENT(this, 0);
  611.         }
  612.  
  613.       nsCOMPtr( const nsCOMPtr<T>& aSmartPtr )
  614.             : NSCAP_CTOR_BASE(aSmartPtr.mRawPtr)
  615.           // copy-constructor
  616.         {
  617.           if ( mRawPtr )
  618.             NSCAP_ADDREF(this, mRawPtr);
  619.           NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
  620.         }
  621.  
  622.       nsCOMPtr( T* aRawPtr )
  623.             : NSCAP_CTOR_BASE(aRawPtr)
  624.           // construct from a raw pointer (of the right type)
  625.         {
  626.           if ( mRawPtr )
  627.             NSCAP_ADDREF(this, mRawPtr);
  628.           NSCAP_LOG_ASSIGNMENT(this, aRawPtr);
  629.           NSCAP_ASSERT_NO_QUERY_NEEDED();
  630.         }
  631.  
  632.       nsCOMPtr( const already_AddRefed<T>& aSmartPtr )
  633.             : NSCAP_CTOR_BASE(aSmartPtr.mRawPtr)
  634.           // construct from |dont_AddRef(expr)|
  635.         {
  636.           NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
  637.           NSCAP_ASSERT_NO_QUERY_NEEDED();
  638.         }
  639.  
  640.       nsCOMPtr( const nsQueryInterface qi )
  641.             : NSCAP_CTOR_BASE(0)
  642.           // construct from |do_QueryInterface(expr)|
  643.         {
  644.           NSCAP_LOG_ASSIGNMENT(this, 0);
  645.           assign_from_qi(qi, NS_GET_IID(T));
  646.         }
  647.  
  648.       nsCOMPtr( const nsQueryInterfaceWithError& qi )
  649.             : NSCAP_CTOR_BASE(0)
  650.           // construct from |do_QueryInterface(expr, &rv)|
  651.         {
  652.           NSCAP_LOG_ASSIGNMENT(this, 0);
  653.           assign_from_qi_with_error(qi, NS_GET_IID(T));
  654.         }
  655.  
  656.       nsCOMPtr( const nsGetServiceByCID gs )
  657.             : NSCAP_CTOR_BASE(0)
  658.           // construct from |do_GetService(cid_expr)|
  659.         {
  660.           NSCAP_LOG_ASSIGNMENT(this, 0);
  661.           assign_from_gs_cid(gs, NS_GET_IID(T));
  662.         }
  663.  
  664.       nsCOMPtr( const nsGetServiceByCIDWithError& gs )
  665.             : NSCAP_CTOR_BASE(0)
  666.           // construct from |do_GetService(cid_expr, &rv)|
  667.         {
  668.           NSCAP_LOG_ASSIGNMENT(this, 0);
  669.           assign_from_gs_cid_with_error(gs, NS_GET_IID(T));
  670.         }
  671.  
  672.       nsCOMPtr( const nsGetServiceByContractID gs )
  673.             : NSCAP_CTOR_BASE(0)
  674.           // construct from |do_GetService(contractid_expr)|
  675.         {
  676.           NSCAP_LOG_ASSIGNMENT(this, 0);
  677.           assign_from_gs_contractid(gs, NS_GET_IID(T));
  678.         }
  679.  
  680.       nsCOMPtr( const nsGetServiceByContractIDWithError& gs )
  681.             : NSCAP_CTOR_BASE(0)
  682.           // construct from |do_GetService(contractid_expr, &rv)|
  683.         {
  684.           NSCAP_LOG_ASSIGNMENT(this, 0);
  685.           assign_from_gs_contractid_with_error(gs, NS_GET_IID(T));
  686.         }
  687.  
  688.       nsCOMPtr( const nsCOMPtr_helper& helper )
  689.             : NSCAP_CTOR_BASE(0)
  690.           // ...and finally, anything else we might need to construct from
  691.           //  can exploit the |nsCOMPtr_helper| facility
  692.         {
  693.           NSCAP_LOG_ASSIGNMENT(this, 0);
  694.           assign_from_helper(helper, NS_GET_IID(T));
  695.           NSCAP_ASSERT_NO_QUERY_NEEDED();
  696.         }
  697.  
  698.  
  699.         // Assignment operators
  700.  
  701.       nsCOMPtr<T>&
  702.       operator=( const nsCOMPtr<T>& rhs )
  703.           // copy assignment operator
  704.         {
  705.           assign_with_AddRef(rhs.mRawPtr);
  706.           return *this;
  707.         }
  708.  
  709.       nsCOMPtr<T>&
  710.       operator=( T* rhs )
  711.           // assign from a raw pointer (of the right type)
  712.         {
  713.           assign_with_AddRef(rhs);
  714.           NSCAP_ASSERT_NO_QUERY_NEEDED();
  715.           return *this;
  716.         }
  717.  
  718.       nsCOMPtr<T>&
  719.       operator=( const already_AddRefed<T>& rhs )
  720.           // assign from |dont_AddRef(expr)|
  721.         {
  722.           assign_assuming_AddRef(rhs.mRawPtr);
  723.           NSCAP_ASSERT_NO_QUERY_NEEDED();
  724.           return *this;
  725.         }
  726.  
  727.       nsCOMPtr<T>&
  728.       operator=( const nsQueryInterface rhs )
  729.           // assign from |do_QueryInterface(expr)|
  730.         {
  731.           assign_from_qi(rhs, NS_GET_IID(T));
  732.           return *this;
  733.         }
  734.  
  735.       nsCOMPtr<T>&
  736.       operator=( const nsQueryInterfaceWithError& rhs )
  737.           // assign from |do_QueryInterface(expr, &rv)|
  738.         {
  739.           assign_from_qi_with_error(rhs, NS_GET_IID(T));
  740.           return *this;
  741.         }
  742.  
  743.       nsCOMPtr<T>&
  744.       operator=( const nsGetServiceByCID rhs )
  745.           // assign from |do_GetService(cid_expr)|
  746.         {
  747.           assign_from_gs_cid(rhs, NS_GET_IID(T));
  748.           return *this;
  749.         }
  750.  
  751.       nsCOMPtr<T>&
  752.       operator=( const nsGetServiceByCIDWithError& rhs )
  753.           // assign from |do_GetService(cid_expr, &rv)|
  754.         {
  755.           assign_from_gs_cid_with_error(rhs, NS_GET_IID(T));
  756.           return *this;
  757.         }
  758.  
  759.       nsCOMPtr<T>&
  760.       operator=( const nsGetServiceByContractID rhs )
  761.           // assign from |do_GetService(contractid_expr)|
  762.         {
  763.           assign_from_gs_contractid(rhs, NS_GET_IID(T));
  764.           return *this;
  765.         }
  766.  
  767.       nsCOMPtr<T>&
  768.       operator=( const nsGetServiceByContractIDWithError& rhs )
  769.           // assign from |do_GetService(contractid_expr, &rv)|
  770.         {
  771.           assign_from_gs_contractid_with_error(rhs, NS_GET_IID(T));
  772.           return *this;
  773.         }
  774.  
  775.       nsCOMPtr<T>&
  776.       operator=( const nsCOMPtr_helper& rhs )
  777.           // ...and finally, anything else we might need to assign from
  778.           //  can exploit the |nsCOMPtr_helper| facility.
  779.         {
  780.           assign_from_helper(rhs, NS_GET_IID(T));
  781.           NSCAP_ASSERT_NO_QUERY_NEEDED();
  782.           return *this;
  783.         }
  784.  
  785.       void
  786.       swap( nsCOMPtr<T>& rhs )
  787.           // ...exchange ownership with |rhs|; can save a pair of refcount operations
  788.         {
  789. #ifdef NSCAP_FEATURE_USE_BASE
  790.           nsISupports* temp = rhs.mRawPtr;
  791. #else
  792.           T* temp = rhs.mRawPtr;
  793. #endif
  794.           NSCAP_LOG_ASSIGNMENT(&rhs, mRawPtr);
  795.           NSCAP_LOG_ASSIGNMENT(this, temp);
  796.           NSCAP_LOG_RELEASE(this, mRawPtr);
  797.           NSCAP_LOG_RELEASE(&rhs, temp);
  798.           rhs.mRawPtr = mRawPtr;
  799.           mRawPtr = temp;
  800.           // |rhs| maintains the same invariants, so we don't need to |NSCAP_ASSERT_NO_QUERY_NEEDED|
  801.         }
  802.  
  803.       void
  804.       swap( T*& rhs )
  805.           // ...exchange ownership with |rhs|; can save a pair of refcount operations
  806.         {
  807. #ifdef NSCAP_FEATURE_USE_BASE
  808.           nsISupports* temp = rhs;
  809. #else
  810.           T* temp = rhs;
  811. #endif
  812.           NSCAP_LOG_ASSIGNMENT(this, temp);
  813.           NSCAP_LOG_RELEASE(this, mRawPtr);
  814.           rhs = NS_REINTERPRET_CAST(T*, mRawPtr);
  815.           mRawPtr = temp;
  816.           NSCAP_ASSERT_NO_QUERY_NEEDED();
  817.         }
  818.  
  819.  
  820.         // Other pointer operators
  821.  
  822.       nsDerivedSafe<T>*
  823.       get() const
  824.           /*
  825.             Prefer the implicit conversion provided automatically by |operator nsDerivedSafe<T>*() const|.
  826.              Use |get()| _only_ to resolve ambiguity.
  827.  
  828.             Returns a |nsDerivedSafe<T>*| to deny clients the use of |AddRef| and |Release|.
  829.           */
  830.         {
  831.           return NS_REINTERPRET_CAST(nsDerivedSafe<T>*, mRawPtr);
  832.         }
  833.  
  834.       operator nsDerivedSafe<T>*() const
  835.           /*
  836.             ...makes an |nsCOMPtr| act like its underlying raw pointer type (except against |AddRef()|, |Release()|,
  837.               and |delete|) whenever it is used in a context where a raw pointer is expected.  It is this operator
  838.               that makes an |nsCOMPtr| substitutable for a raw pointer.
  839.  
  840.             Prefer the implicit use of this operator to calling |get()|, except where necessary to resolve ambiguity.
  841.           */
  842.         {
  843.           return get();
  844.         }
  845.  
  846.       nsDerivedSafe<T>*
  847.       operator->() const
  848.         {
  849.           NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator->().");
  850.           return get();
  851.         }
  852.  
  853. #ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
  854.   // broken version for IRIX
  855.  
  856.       nsCOMPtr<T>*
  857.       get_address() const
  858.           // This is not intended to be used by clients.  See |address_of|
  859.           // below.
  860.         {
  861.           return NS_CONST_CAST(nsCOMPtr<T>*, this);
  862.         }
  863.  
  864. #else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
  865.  
  866.       nsCOMPtr<T>*
  867.       get_address()
  868.           // This is not intended to be used by clients.  See |address_of|
  869.           // below.
  870.         {
  871.           return this;
  872.         }
  873.  
  874.       const nsCOMPtr<T>*
  875.       get_address() const
  876.           // This is not intended to be used by clients.  See |address_of|
  877.           // below.
  878.         {
  879.           return this;
  880.         }
  881.  
  882. #endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
  883.  
  884.     public:
  885.       nsDerivedSafe<T>&
  886.       operator*() const
  887.         {
  888.           NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator*().");
  889.           return *get();
  890.         }
  891.  
  892. #if 0
  893.     private:
  894.       friend class nsGetterAddRefs<T>;
  895. #endif
  896.  
  897.       T**
  898.       StartAssignment()
  899.         {
  900. #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
  901.           return NS_REINTERPRET_CAST(T**, begin_assignment());
  902. #else
  903.           assign_assuming_AddRef(0);
  904.           return NS_REINTERPRET_CAST(T**, &mRawPtr);
  905. #endif
  906.         }
  907.   };
  908.  
  909.  
  910.  
  911.   /*
  912.     Specializing |nsCOMPtr| for |nsISupports| allows us to use |nsCOMPtr<nsISupports>| the
  913.     same way people use |nsISupports*| and |void*|, i.e., as a `catch-all' pointer pointing
  914.     to any valid [XP]COM interface.  Otherwise, an |nsCOMPtr<nsISupports>| would only be able
  915.     to point to the single [XP]COM-correct |nsISupports| instance within an object; extra
  916.     querying ensues.  Clients need to be able to pass around arbitrary interface pointers,
  917.     without hassles, through intermediary code that doesn't know the exact type.
  918.   */
  919.  
  920. NS_SPECIALIZE_TEMPLATE
  921. class nsCOMPtr<nsISupports>
  922.     : private nsCOMPtr_base
  923.   {
  924.     public:
  925.       typedef nsISupports element_type;
  926.  
  927.         // Constructors
  928.  
  929.       nsCOMPtr()
  930.             : nsCOMPtr_base(0)
  931.           // default constructor
  932.         {
  933.           NSCAP_LOG_ASSIGNMENT(this, 0);
  934.         }
  935.  
  936.       nsCOMPtr( const nsCOMPtr<nsISupports>& aSmartPtr )
  937.             : nsCOMPtr_base(aSmartPtr.mRawPtr)
  938.           // copy constructor
  939.         {
  940.           if ( mRawPtr )
  941.             NSCAP_ADDREF(this, mRawPtr);
  942.           NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
  943.         }
  944.  
  945.       nsCOMPtr( nsISupports* aRawPtr )
  946.             : nsCOMPtr_base(aRawPtr)
  947.           // construct from a raw pointer (of the right type)
  948.         {
  949.           if ( mRawPtr )
  950.             NSCAP_ADDREF(this, mRawPtr);
  951.           NSCAP_LOG_ASSIGNMENT(this, aRawPtr);
  952.         }
  953.  
  954.       nsCOMPtr( const already_AddRefed<nsISupports>& aSmartPtr )
  955.             : nsCOMPtr_base(aSmartPtr.mRawPtr)
  956.           // construct from |dont_AddRef(expr)|
  957.         {
  958.           NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
  959.         }
  960.  
  961.       nsCOMPtr( const nsQueryInterface qi )
  962.             : nsCOMPtr_base(0)
  963.           // assign from |do_QueryInterface(expr)|
  964.         {
  965.           NSCAP_LOG_ASSIGNMENT(this, 0);
  966.           assign_from_qi(qi, NS_GET_IID(nsISupports));
  967.         }
  968.  
  969.       nsCOMPtr( const nsQueryInterfaceWithError& qi )
  970.             : nsCOMPtr_base(0)
  971.           // assign from |do_QueryInterface(expr, &rv)|
  972.         {
  973.           NSCAP_LOG_ASSIGNMENT(this, 0);
  974.           assign_from_qi_with_error(qi, NS_GET_IID(nsISupports));
  975.         }
  976.  
  977.       nsCOMPtr( const nsGetServiceByCID gs )
  978.             : nsCOMPtr_base(0)
  979.           // assign from |do_GetService(cid_expr)|
  980.         {
  981.           NSCAP_LOG_ASSIGNMENT(this, 0);
  982.           assign_from_gs_cid(gs, NS_GET_IID(nsISupports));
  983.         }
  984.  
  985.       nsCOMPtr( const nsGetServiceByCIDWithError& gs )
  986.             : nsCOMPtr_base(0)
  987.           // assign from |do_GetService(cid_expr, &rv)|
  988.         {
  989.           NSCAP_LOG_ASSIGNMENT(this, 0);
  990.           assign_from_gs_cid_with_error(gs, NS_GET_IID(nsISupports));
  991.         }
  992.  
  993.       nsCOMPtr( const nsGetServiceByContractID gs )
  994.             : nsCOMPtr_base(0)
  995.           // assign from |do_GetService(contractid_expr)|
  996.         {
  997.           NSCAP_LOG_ASSIGNMENT(this, 0);
  998.           assign_from_gs_contractid(gs, NS_GET_IID(nsISupports));
  999.         }
  1000.  
  1001.       nsCOMPtr( const nsGetServiceByContractIDWithError& gs )
  1002.             : nsCOMPtr_base(0)
  1003.           // assign from |do_GetService(contractid_expr, &rv)|
  1004.         {
  1005.           NSCAP_LOG_ASSIGNMENT(this, 0);
  1006.           assign_from_gs_contractid_with_error(gs, NS_GET_IID(nsISupports));
  1007.         }
  1008.  
  1009.       nsCOMPtr( const nsCOMPtr_helper& helper )
  1010.             : nsCOMPtr_base(0)
  1011.           // ...and finally, anything else we might need to construct from
  1012.           //  can exploit the |nsCOMPtr_helper| facility
  1013.         {
  1014.           NSCAP_LOG_ASSIGNMENT(this, 0);
  1015.           assign_from_helper(helper, NS_GET_IID(nsISupports));
  1016.         }
  1017.  
  1018.  
  1019.         // Assignment operators
  1020.  
  1021.       nsCOMPtr<nsISupports>&
  1022.       operator=( const nsCOMPtr<nsISupports>& rhs )
  1023.           // copy assignment operator
  1024.         {
  1025.           assign_with_AddRef(rhs.mRawPtr);
  1026.           return *this;
  1027.         }
  1028.  
  1029.       nsCOMPtr<nsISupports>&
  1030.       operator=( nsISupports* rhs )
  1031.           // assign from a raw pointer (of the right type)
  1032.         {
  1033.           assign_with_AddRef(rhs);
  1034.           return *this;
  1035.         }
  1036.  
  1037.       nsCOMPtr<nsISupports>&
  1038.       operator=( const already_AddRefed<nsISupports>& rhs )
  1039.           // assign from |dont_AddRef(expr)|
  1040.         {
  1041.           assign_assuming_AddRef(rhs.mRawPtr);
  1042.           return *this;
  1043.         }
  1044.  
  1045.       nsCOMPtr<nsISupports>&
  1046.       operator=( const nsQueryInterface rhs )
  1047.           // assign from |do_QueryInterface(expr)|
  1048.         {
  1049.           assign_from_qi(rhs, NS_GET_IID(nsISupports));
  1050.           return *this;
  1051.         }
  1052.  
  1053.       nsCOMPtr<nsISupports>&
  1054.       operator=( const nsQueryInterfaceWithError& rhs )
  1055.           // assign from |do_QueryInterface(expr, &rv)|
  1056.         {
  1057.           assign_from_qi_with_error(rhs, NS_GET_IID(nsISupports));
  1058.           return *this;
  1059.         }
  1060.  
  1061.       nsCOMPtr<nsISupports>&
  1062.       operator=( const nsGetServiceByCID rhs )
  1063.           // assign from |do_GetService(cid_expr)|
  1064.         {
  1065.           assign_from_gs_cid(rhs, NS_GET_IID(nsISupports));
  1066.           return *this;
  1067.         }
  1068.  
  1069.       nsCOMPtr<nsISupports>&
  1070.       operator=( const nsGetServiceByCIDWithError& rhs )
  1071.           // assign from |do_GetService(cid_expr, &rv)|
  1072.         {
  1073.           assign_from_gs_cid_with_error(rhs, NS_GET_IID(nsISupports));
  1074.           return *this;
  1075.         }
  1076.  
  1077.       nsCOMPtr<nsISupports>&
  1078.       operator=( const nsGetServiceByContractID rhs )
  1079.           // assign from |do_GetService(contractid_expr)|
  1080.         {
  1081.           assign_from_gs_contractid(rhs, NS_GET_IID(nsISupports));
  1082.           return *this;
  1083.         }
  1084.  
  1085.       nsCOMPtr<nsISupports>&
  1086.       operator=( const nsGetServiceByContractIDWithError& rhs )
  1087.           // assign from |do_GetService(contractid_expr, &rv)|
  1088.         {
  1089.           assign_from_gs_contractid_with_error(rhs, NS_GET_IID(nsISupports));
  1090.           return *this;
  1091.         }
  1092.  
  1093.       nsCOMPtr<nsISupports>&
  1094.       operator=( const nsCOMPtr_helper& rhs )
  1095.           // ...and finally, anything else we might need to assign from
  1096.           //  can exploit the |nsCOMPtr_helper| facility.
  1097.         {
  1098.           assign_from_helper(rhs, NS_GET_IID(nsISupports));
  1099.           return *this;
  1100.         }
  1101.  
  1102.       void
  1103.       swap( nsCOMPtr<nsISupports>& rhs )
  1104.           // ...exchange ownership with |rhs|; can save a pair of refcount operations
  1105.         {
  1106.           nsISupports* temp = rhs.mRawPtr;
  1107.           NSCAP_LOG_ASSIGNMENT(&rhs, mRawPtr);
  1108.           NSCAP_LOG_ASSIGNMENT(this, temp);
  1109.           NSCAP_LOG_RELEASE(this, mRawPtr);
  1110.           NSCAP_LOG_RELEASE(&rhs, temp);
  1111.           rhs.mRawPtr = mRawPtr;
  1112.           mRawPtr = temp;
  1113.         }
  1114.  
  1115.       void
  1116.       swap( nsISupports*& rhs )
  1117.           // ...exchange ownership with |rhs|; can save a pair of refcount operations
  1118.         {
  1119.           nsISupports* temp = rhs;
  1120.           NSCAP_LOG_ASSIGNMENT(this, temp);
  1121.           NSCAP_LOG_RELEASE(this, mRawPtr);
  1122.           rhs = mRawPtr;
  1123.           mRawPtr = temp;
  1124.         }
  1125.  
  1126.  
  1127.         // Other pointer operators
  1128.  
  1129.       nsDerivedSafe<nsISupports>*
  1130.       get() const
  1131.           /*
  1132.             Prefer the implicit conversion provided automatically by |operator nsDerivedSafe<nsISupports>*() const|.
  1133.              Use |get()| _only_ to resolve ambiguity.
  1134.  
  1135.             Returns a |nsDerivedSafe<nsISupports>*| to deny clients the use of |AddRef| and |Release|.
  1136.           */
  1137.         {
  1138.           return NS_REINTERPRET_CAST(nsDerivedSafe<nsISupports>*, mRawPtr);
  1139.         }
  1140.  
  1141.       operator nsDerivedSafe<nsISupports>*() const
  1142.           /*
  1143.             ...makes an |nsCOMPtr| act like its underlying raw pointer type (except against |AddRef()|, |Release()|,
  1144.               and |delete|) whenever it is used in a context where a raw pointer is expected.  It is this operator
  1145.               that makes an |nsCOMPtr| substitutable for a raw pointer.
  1146.  
  1147.             Prefer the implicit use of this operator to calling |get()|, except where necessary to resolve ambiguity.
  1148.           */
  1149.         {
  1150.           return get();
  1151.         }
  1152.  
  1153.       nsDerivedSafe<nsISupports>*
  1154.       operator->() const
  1155.         {
  1156.           NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator->().");
  1157.           return get();
  1158.         }
  1159.  
  1160. #ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
  1161.   // broken version for IRIX
  1162.  
  1163.       nsCOMPtr<nsISupports>*
  1164.       get_address() const
  1165.           // This is not intended to be used by clients.  See |address_of|
  1166.           // below.
  1167.         {
  1168.           return NS_CONST_CAST(nsCOMPtr<nsISupports>*, this);
  1169.         }
  1170.  
  1171. #else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
  1172.  
  1173.       nsCOMPtr<nsISupports>*
  1174.       get_address()
  1175.           // This is not intended to be used by clients.  See |address_of|
  1176.           // below.
  1177.         {
  1178.           return this;
  1179.         }
  1180.  
  1181.       const nsCOMPtr<nsISupports>*
  1182.       get_address() const
  1183.           // This is not intended to be used by clients.  See |address_of|
  1184.           // below.
  1185.         {
  1186.           return this;
  1187.         }
  1188.  
  1189. #endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
  1190.  
  1191.     public:
  1192.  
  1193.       nsDerivedSafe<nsISupports>&
  1194.       operator*() const
  1195.         {
  1196.           NS_PRECONDITION(mRawPtr != 0, "You can't dereference a NULL nsCOMPtr with operator*().");
  1197.           return *get();
  1198.         }
  1199.  
  1200. #if 0
  1201.     private:
  1202.       friend class nsGetterAddRefs<nsISupports>;
  1203. #endif
  1204.  
  1205.       nsISupports**
  1206.       StartAssignment()
  1207.         {
  1208. #ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
  1209.           return NS_REINTERPRET_CAST(nsISupports**, begin_assignment());
  1210. #else
  1211.           assign_assuming_AddRef(0);
  1212.           return NS_REINTERPRET_CAST(nsISupports**, &mRawPtr);
  1213. #endif
  1214.         }
  1215.   };
  1216.  
  1217. #ifndef NSCAP_FEATURE_USE_BASE
  1218. template <class T>
  1219. void
  1220. nsCOMPtr<T>::assign_with_AddRef( nsISupports* rawPtr )
  1221.   {
  1222.     if ( rawPtr )
  1223.       NSCAP_ADDREF(this, rawPtr);
  1224.     assign_assuming_AddRef(NS_REINTERPRET_CAST(T*, rawPtr));
  1225.   }
  1226.  
  1227. template <class T>
  1228. void
  1229. nsCOMPtr<T>::assign_from_qi( const nsQueryInterface qi, const nsIID& aIID )
  1230.   {
  1231.     T* newRawPtr;
  1232.     if ( NS_FAILED( qi(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
  1233.       newRawPtr = 0;
  1234.     assign_assuming_AddRef(newRawPtr);
  1235.   }
  1236.  
  1237. template <class T>
  1238. void
  1239. nsCOMPtr<T>::assign_from_qi_with_error( const nsQueryInterfaceWithError& qi, const nsIID& aIID )
  1240.   {
  1241.     T* newRawPtr;
  1242.     if ( NS_FAILED( qi(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
  1243.       newRawPtr = 0;
  1244.     assign_assuming_AddRef(newRawPtr);
  1245.   }
  1246.  
  1247. template <class T>
  1248. void
  1249. nsCOMPtr<T>::assign_from_gs_cid( const nsGetServiceByCID gs, const nsIID& aIID )
  1250.   {
  1251.     T* newRawPtr;
  1252.     if ( NS_FAILED( gs(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
  1253.       newRawPtr = 0;
  1254.     assign_assuming_AddRef(newRawPtr);
  1255.   }
  1256.  
  1257. template <class T>
  1258. void
  1259. nsCOMPtr<T>::assign_from_gs_cid_with_error( const nsGetServiceByCIDWithError& gs, const nsIID& aIID )
  1260.   {
  1261.     T* newRawPtr;
  1262.     if ( NS_FAILED( gs(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
  1263.       newRawPtr = 0;
  1264.     assign_assuming_AddRef(newRawPtr);
  1265.   }
  1266.  
  1267. template <class T>
  1268. void
  1269. nsCOMPtr<T>::assign_from_gs_contractid( const nsGetServiceByContractID gs, const nsIID& aIID )
  1270.   {
  1271.     T* newRawPtr;
  1272.     if ( NS_FAILED( gs(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
  1273.       newRawPtr = 0;
  1274.     assign_assuming_AddRef(newRawPtr);
  1275.   }
  1276.  
  1277. template <class T>
  1278. void
  1279. nsCOMPtr<T>::assign_from_gs_contractid_with_error( const nsGetServiceByContractIDWithError& gs, const nsIID& aIID )
  1280.   {
  1281.     T* newRawPtr;
  1282.     if ( NS_FAILED( gs(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
  1283.       newRawPtr = 0;
  1284.     assign_assuming_AddRef(newRawPtr);
  1285.   }
  1286.  
  1287. template <class T>
  1288. void
  1289. nsCOMPtr<T>::assign_from_helper( const nsCOMPtr_helper& helper, const nsIID& aIID )
  1290.   {
  1291.     T* newRawPtr;
  1292.     if ( NS_FAILED( helper(aIID, NS_REINTERPRET_CAST(void**, &newRawPtr)) ) )
  1293.       newRawPtr = 0;
  1294.     assign_assuming_AddRef(newRawPtr);
  1295.   }
  1296.  
  1297. template <class T>
  1298. void**
  1299. nsCOMPtr<T>::begin_assignment()
  1300.   {
  1301.     assign_assuming_AddRef(0);
  1302.     return NS_REINTERPRET_CAST(void**, &mRawPtr);
  1303.   }
  1304. #endif
  1305.  
  1306. #ifdef CANT_RESOLVE_CPP_CONST_AMBIGUITY
  1307.  
  1308. // This is the broken version for IRIX, which can't handle the version below.
  1309.  
  1310. template <class T>
  1311. inline
  1312. nsCOMPtr<T>*
  1313. address_of( const nsCOMPtr<T>& aPtr )
  1314.   {
  1315.     return aPtr.get_address();
  1316.   }
  1317.  
  1318. #else // CANT_RESOLVE_CPP_CONST_AMBIGUITY
  1319.  
  1320. template <class T>
  1321. inline
  1322. nsCOMPtr<T>*
  1323. address_of( nsCOMPtr<T>& aPtr )
  1324.   {
  1325.     return aPtr.get_address();
  1326.   }
  1327.  
  1328. template <class T>
  1329. inline
  1330. const nsCOMPtr<T>*
  1331. address_of( const nsCOMPtr<T>& aPtr )
  1332.   {
  1333.     return aPtr.get_address();
  1334.   }
  1335.  
  1336. #endif // CANT_RESOLVE_CPP_CONST_AMBIGUITY
  1337.  
  1338. template <class T>
  1339. class nsGetterAddRefs
  1340.     /*
  1341.       ...
  1342.  
  1343.       This class is designed to be used for anonymous temporary objects in the
  1344.       argument list of calls that return COM interface pointers, e.g.,
  1345.  
  1346.         nsCOMPtr<IFoo> fooP;
  1347.         ...->QueryInterface(iid, getter_AddRefs(fooP))
  1348.  
  1349.       DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE.  Use |getter_AddRefs()| instead.
  1350.  
  1351.       When initialized with a |nsCOMPtr|, as in the example above, it returns
  1352.       a |void**|, a |T**|, or an |nsISupports**| as needed, that the outer call (|QueryInterface| in this
  1353.       case) can fill in.
  1354.  
  1355.       This type should be a nested class inside |nsCOMPtr<T>|.
  1356.     */
  1357.   {
  1358.     public:
  1359.       explicit
  1360.       nsGetterAddRefs( nsCOMPtr<T>& aSmartPtr )
  1361.           : mTargetSmartPtr(aSmartPtr)
  1362.         {
  1363.           // nothing else to do
  1364.         }
  1365.  
  1366. #if defined(NSCAP_FEATURE_TEST_DONTQUERY_CASES) || defined(NSCAP_LOG_EXTERNAL_ASSIGNMENT)
  1367.      ~nsGetterAddRefs()
  1368.         {
  1369. #ifdef NSCAP_LOG_EXTERNAL_ASSIGNMENT
  1370.           NSCAP_LOG_ASSIGNMENT(NS_REINTERPRET_CAST(void *, address_of(mTargetSmartPtr)), mTargetSmartPtr.get());
  1371. #endif
  1372.  
  1373. #ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES
  1374.           mTargetSmartPtr.Assert_NoQueryNeeded();
  1375. #endif
  1376.         }
  1377. #endif
  1378.  
  1379.       operator void**()
  1380.         {
  1381.           return NS_REINTERPRET_CAST(void**, mTargetSmartPtr.StartAssignment());
  1382.         }
  1383.  
  1384.       operator nsISupports**()
  1385.         {
  1386.           return NS_REINTERPRET_CAST(nsISupports**, mTargetSmartPtr.StartAssignment());
  1387.         }
  1388.  
  1389.       operator T**()
  1390.         {
  1391.           return mTargetSmartPtr.StartAssignment();
  1392.         }
  1393.  
  1394.       T*&
  1395.       operator*()
  1396.         {
  1397.           return *(mTargetSmartPtr.StartAssignment());
  1398.         }
  1399.  
  1400.     private:
  1401.       nsCOMPtr<T>& mTargetSmartPtr;
  1402.   };
  1403.  
  1404.  
  1405. NS_SPECIALIZE_TEMPLATE
  1406. class nsGetterAddRefs<nsISupports>
  1407.   {
  1408.     public:
  1409.       explicit
  1410.       nsGetterAddRefs( nsCOMPtr<nsISupports>& aSmartPtr )
  1411.           : mTargetSmartPtr(aSmartPtr)
  1412.         {
  1413.           // nothing else to do
  1414.         }
  1415.  
  1416. #ifdef NSCAP_LOG_EXTERNAL_ASSIGNMENT
  1417.      ~nsGetterAddRefs()
  1418.         {
  1419.           NSCAP_LOG_ASSIGNMENT(NS_REINTERPRET_CAST(void *, address_of(mTargetSmartPtr)), mTargetSmartPtr.get());
  1420.         }
  1421. #endif
  1422.  
  1423.       operator void**()
  1424.         {
  1425.           return NS_REINTERPRET_CAST(void**, mTargetSmartPtr.StartAssignment());
  1426.         }
  1427.  
  1428.       operator nsISupports**()
  1429.         {
  1430.           return mTargetSmartPtr.StartAssignment();
  1431.         }
  1432.  
  1433.       nsISupports*&
  1434.       operator*()
  1435.         {
  1436.           return *(mTargetSmartPtr.StartAssignment());
  1437.         }
  1438.  
  1439.     private:
  1440.       nsCOMPtr<nsISupports>& mTargetSmartPtr;
  1441.   };
  1442.  
  1443.  
  1444. template <class T>
  1445. inline
  1446. nsGetterAddRefs<T>
  1447. getter_AddRefs( nsCOMPtr<T>& aSmartPtr )
  1448.     /*
  1449.       Used around a |nsCOMPtr| when 
  1450.       ...makes the class |nsGetterAddRefs<T>| invisible.
  1451.     */
  1452.   {
  1453.     return nsGetterAddRefs<T>(aSmartPtr);
  1454.   }
  1455.  
  1456.  
  1457.  
  1458.   // Comparing two |nsCOMPtr|s
  1459.  
  1460. template <class T, class U>
  1461. inline
  1462. NSCAP_BOOL
  1463. operator==( const nsCOMPtr<T>& lhs, const nsCOMPtr<U>& rhs )
  1464.   {
  1465.     return NS_STATIC_CAST(const T*, lhs.get()) == NS_STATIC_CAST(const U*, rhs.get());
  1466.   }
  1467.  
  1468.  
  1469. template <class T, class U>
  1470. inline
  1471. NSCAP_BOOL
  1472. operator!=( const nsCOMPtr<T>& lhs, const nsCOMPtr<U>& rhs )
  1473.   {
  1474.     return NS_STATIC_CAST(const T*, lhs.get()) != NS_STATIC_CAST(const U*, rhs.get());
  1475.   }
  1476.  
  1477.  
  1478.   // Comparing an |nsCOMPtr| to a raw pointer
  1479.  
  1480. template <class T, class U>
  1481. inline
  1482. NSCAP_BOOL
  1483. operator==( const nsCOMPtr<T>& lhs, const U* rhs )
  1484.   {
  1485.     return NS_STATIC_CAST(const T*, lhs.get()) == rhs;
  1486.   }
  1487.  
  1488. template <class T, class U>
  1489. inline
  1490. NSCAP_BOOL
  1491. operator==( const U* lhs, const nsCOMPtr<T>& rhs )
  1492.   {
  1493.     return lhs == NS_STATIC_CAST(const T*, rhs.get());
  1494.   }
  1495.  
  1496. template <class T, class U>
  1497. inline
  1498. NSCAP_BOOL
  1499. operator!=( const nsCOMPtr<T>& lhs, const U* rhs )
  1500.   {
  1501.     return NS_STATIC_CAST(const T*, lhs.get()) != rhs;
  1502.   }
  1503.  
  1504. template <class T, class U>
  1505. inline
  1506. NSCAP_BOOL
  1507. operator!=( const U* lhs, const nsCOMPtr<T>& rhs )
  1508.   {
  1509.     return lhs != NS_STATIC_CAST(const T*, rhs.get());
  1510.   }
  1511.  
  1512.   // To avoid ambiguities caused by the presence of builtin |operator==|s
  1513.   // creating a situation where one of the |operator==| defined above
  1514.   // has a better conversion for one argument and the builtin has a
  1515.   // better conversion for the other argument, define additional
  1516.   // |operator==| without the |const| on the raw pointer.
  1517.   // See bug 65664 for details.
  1518.  
  1519. // This is defined by an autoconf test, but VC++ also has a bug that
  1520. // prevents us from using these.  (It also, fortunately, has the bug
  1521. // that we don't need them either.)
  1522. #if defined(_MSC_VER) && (_MSC_VER < 1310)
  1523. #ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ
  1524. #define NSCAP_DONT_PROVIDE_NONCONST_OPEQ
  1525. #endif
  1526. #endif
  1527.  
  1528. #ifndef NSCAP_DONT_PROVIDE_NONCONST_OPEQ
  1529. template <class T, class U>
  1530. inline
  1531. NSCAP_BOOL
  1532. operator==( const nsCOMPtr<T>& lhs, U* rhs )
  1533.   {
  1534.     return NS_STATIC_CAST(const T*, lhs.get()) == NS_CONST_CAST(const U*, rhs);
  1535.   }
  1536.  
  1537. template <class T, class U>
  1538. inline
  1539. NSCAP_BOOL
  1540. operator==( U* lhs, const nsCOMPtr<T>& rhs )
  1541.   {
  1542.     return NS_CONST_CAST(const U*, lhs) == NS_STATIC_CAST(const T*, rhs.get());
  1543.   }
  1544.  
  1545. template <class T, class U>
  1546. inline
  1547. NSCAP_BOOL
  1548. operator!=( const nsCOMPtr<T>& lhs, U* rhs )
  1549.   {
  1550.     return NS_STATIC_CAST(const T*, lhs.get()) != NS_CONST_CAST(const U*, rhs);
  1551.   }
  1552.  
  1553. template <class T, class U>
  1554. inline
  1555. NSCAP_BOOL
  1556. operator!=( U* lhs, const nsCOMPtr<T>& rhs )
  1557.   {
  1558.     return NS_CONST_CAST(const U*, lhs) != NS_STATIC_CAST(const T*, rhs.get());
  1559.   }
  1560. #endif
  1561.  
  1562.  
  1563.  
  1564.   // Comparing an |nsCOMPtr| to |0|
  1565.  
  1566. class NSCAP_Zero;
  1567.  
  1568. template <class T>
  1569. inline
  1570. NSCAP_BOOL
  1571. operator==( const nsCOMPtr<T>& lhs, NSCAP_Zero* rhs )
  1572.     // specifically to allow |smartPtr == 0|
  1573.   {
  1574.     return NS_STATIC_CAST(const void*, lhs.get()) == NS_REINTERPRET_CAST(const void*, rhs);
  1575.   }
  1576.  
  1577. template <class T>
  1578. inline
  1579. NSCAP_BOOL
  1580. operator==( NSCAP_Zero* lhs, const nsCOMPtr<T>& rhs )
  1581.     // specifically to allow |0 == smartPtr|
  1582.   {
  1583.     return NS_REINTERPRET_CAST(const void*, lhs) == NS_STATIC_CAST(const void*, rhs.get());
  1584.   }
  1585.  
  1586. template <class T>
  1587. inline
  1588. NSCAP_BOOL
  1589. operator!=( const nsCOMPtr<T>& lhs, NSCAP_Zero* rhs )
  1590.     // specifically to allow |smartPtr != 0|
  1591.   {
  1592.     return NS_STATIC_CAST(const void*, lhs.get()) != NS_REINTERPRET_CAST(const void*, rhs);
  1593.   }
  1594.  
  1595. template <class T>
  1596. inline
  1597. NSCAP_BOOL
  1598. operator!=( NSCAP_Zero* lhs, const nsCOMPtr<T>& rhs )
  1599.     // specifically to allow |0 != smartPtr|
  1600.   {
  1601.     return NS_REINTERPRET_CAST(const void*, lhs) != NS_STATIC_CAST(const void*, rhs.get());
  1602.   }
  1603.  
  1604.  
  1605. #ifdef HAVE_CPP_TROUBLE_COMPARING_TO_ZERO
  1606.  
  1607.   // We need to explicitly define comparison operators for `int'
  1608.   // because the compiler is lame.
  1609.  
  1610. template <class T>
  1611. inline
  1612. NSCAP_BOOL
  1613. operator==( const nsCOMPtr<T>& lhs, int rhs )
  1614.     // specifically to allow |smartPtr == 0|
  1615.   {
  1616.     return NS_STATIC_CAST(const void*, lhs.get()) == NS_REINTERPRET_CAST(const void*, rhs);
  1617.   }
  1618.  
  1619. template <class T>
  1620. inline
  1621. NSCAP_BOOL
  1622. operator==( int lhs, const nsCOMPtr<T>& rhs )
  1623.     // specifically to allow |0 == smartPtr|
  1624.   {
  1625.     return NS_REINTERPRET_CAST(const void*, lhs) == NS_STATIC_CAST(const void*, rhs.get());
  1626.   }
  1627.  
  1628. #endif // !defined(HAVE_CPP_TROUBLE_COMPARING_TO_ZERO)
  1629.  
  1630.   // Comparing any two [XP]COM objects for identity
  1631.  
  1632. inline
  1633. NSCAP_BOOL
  1634. SameCOMIdentity( nsISupports* lhs, nsISupports* rhs )
  1635.   {
  1636.     return nsCOMPtr<nsISupports>( do_QueryInterface(lhs) ) == nsCOMPtr<nsISupports>( do_QueryInterface(rhs) );
  1637.   }
  1638.  
  1639.  
  1640.  
  1641. template <class SourceType, class DestinationType>
  1642. inline
  1643. nsresult
  1644. CallQueryInterface( nsCOMPtr<SourceType>& aSourcePtr, DestinationType** aDestPtr )
  1645.   {
  1646.     return CallQueryInterface(aSourcePtr.get(), aDestPtr);
  1647.   }
  1648.  
  1649. #endif // !defined(nsCOMPtr_h___)
  1650.